package ru.madeira.jtetris;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

/**хранит представление игры*/
public class Game {

    private Field field;
    private static int min_points = 100;
    private GameSession session;
    private int score = 0;
    private int next_lines = 10;
    private int hiscore = 0;
    private int level = 1;
    private int lines_removed = 0;
    private int next_template = 0;
    private int timer_length = 0;
    private int current_block_x = 0;
    private int current_block_y = 0;
    private int next_block = -1;
    private boolean isstate = false;
    private Template current_block;
    private boolean hasMovingBlock;
    private String randomphrase = null;
    private boolean timer_restart = false;
    Timer timer;

    public Game(GameSession gs){
        session = gs;
        field = new Field();
    }

    /**
     * вызывается в начале новой игры
     */
    public void startGame(){
       startTimer(1000);
    }

    /**
     * вызывается при продолжении старой игры
     */
    public void continueGame(){

    }

    /**вызывается про проигрыше
     *
     */
    public void lose(){

    }

    public Field getField() {
        return field;
    }

    public void speedTimer(){
         timer.setDelay(timer_length/10);
         timer_restart = true;
    }

    private void startTimer(int new_length){
       timer_length = new_length;
       timer = new Timer(new_length, new ActionListener() {


           @Override
           public void actionPerformed(ActionEvent e) {
              Game.this.nextTurn();
           }
       });
        timer.start();
    }

    private synchronized void nextTurn(){
        if (!hasMovingBlock) create_block();
        else
            move_block();
    }

    private synchronized void create_block(){
        Random r = new Random();
        int y = 0;
        int x = (field.getWidth()/2) - 2;
        hasMovingBlock = true;
        int block = 0;
        if (next_block==-1){
           block = r.nextInt(TemplateSet.MAX_TILES);
        }
        else
        block = next_block;
        current_block = (Template)TemplateSet.TEMPLATESET[block].clone();
        current_block_x = x;
        current_block_y = y;
        check_block();
        session.updateScreen();
        next_block = r.nextInt(TemplateSet.MAX_TILES);
    }

    private void move_block(){
        current_block_y++;
        check_block();
        session.updateScreen();
    }

    private void delete_line(int j){
        for (int i=0; i<4; i++){
            if (current_block.element[i][j]!=0)
                if (field.hasTileAt(current_block_y + i,current_block_x + j))
                 field.setElement(current_block_y + i,current_block_x + j, current_block.element[i][j]);
            current_block.element[i][j] = 0;
        }

    }

    private void check_block(){
        boolean stuck = false;
        for (int j =0; j<4; j++)
         for (int i = 0; i<4; i++)
            if ((!field.hasTileAt(current_block_y+i+1, current_block_x+j) && current_block.element[i][j]!=0)  || (current_block.element[i][j]!=0 && field.getElement(current_block_y+i+1, current_block_x+j)!=0))
            {

    if (stackOn(current_block_y, current_block_x))
        current_block_y--;

                   for (int j1=0; j1<4; j1++)
                     delete_line(j1);
                     break;
            }

      for (int i=0; i<4; i++)
          for (int j=0; j<4; j++)
              if (current_block.element[i][j]!=0) stuck = true;

          if (!stuck) {
              hasMovingBlock = false;
              timer_restart = false;
              timer.setDelay(timer_length);
              checkforlines();
          }


    }


    private void checkforlines(){
        int l = 0;
        for (int i = field.getHeight() - 1; i > 0 ; ){
            int x = 0;
            for (int j=0; j< field.getWidth(); j++)
                if (field.getElement(i,j)!=0) x++;
            if (x==field.getWidth()) {
                l++;
                delete_row(i);
            }
            else
            i--;
        }
        if (l!=0){
           lines_removed += l;
           next_lines -= l;
            if (next_lines <=0){
                level++;
                timer_length -= 100;
                timer.setDelay(timer_length);
                next_lines = 10 + (level - 1) * 5;
                level_up();
            }
           score += (min_points * Math.pow(2,l));
            Random r = new Random();
           randomphrase = PhrasesSet.SET[r.nextInt(PhrasesSet.SET.length)];
        }

    }


    public void level_up(){

    }

   private void delete_row(int n){
      for (int i = n; i>0; i--)
           for (int j = 0; j<field.getWidth(); j++)
               field.setElement(i,j,field.getElement(i-1,j));
   }

    public int getScore() {
        return score;
    }

    public int getLines_removed() {
        return lines_removed;
    }

    public int getLevel() {
        return level;
    }

    public int getNext_template() {
        return next_template;
    }

    public int getCurrent_block_x() {
        return current_block_x;
    }

    public int getCurrent_block_y() {
        return current_block_y;
    }

    public Template getCurrent_block() {
        return current_block;
    }

    public boolean isHasMovingBlock() {
        return hasMovingBlock;
    }

    public synchronized void setCurrent_block_x(int current_block_x) {
        if (!stackOn(current_block_y, current_block_x))
        this.current_block_x = current_block_x;
        session.updateScreen();
    }

    private synchronized boolean stackOn(int y, int x){
         boolean res = false;
        for (int i = 0; i<4; i++)
            for (int j = 0; j<4; j++)
                if ((!field.hasTileAt(y + i, x + j) && current_block.element[i][j]!=0)||
                (field.hasTileAt(y + i, x + j) && field.getElement(y + i, x + j)!=0 &&  current_block.element[i][j]!=0 ))
                    res = true;

        return res;

    }

    public int getHiscore() {
        return hiscore;
    }

    public int getNext_block() {
        return next_block;
    }

    public synchronized String getRandomphrase() {
        return randomphrase;
    }


    public synchronized void rotate_left(){

            current_block.rotate();
            current_block.rotate();
            current_block.rotate();
            if (stackOn(current_block_y, current_block_x)){
                current_block.rotate();
            }
            session.updateScreen();
        }

    public int getNext_lines() {
        return next_lines;
    }
}
